﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Threading.Tasks;
using Dapper;
using Dapper.Contrib.Extensions;

namespace Topro.Application.Impl
{
    using Topro.Application.Interface;
    using Topro.Db;
    using Topro.Entity;
    using Topro.Entity.Enum;
    using Topro.Entity.Query;
    using Topro.Entity.Request.StockOut;
    using Topro.Entity.Response.Inventory;
    using Topro.Entity.Response.StockOut;
    using Topro.Entity.Tables;
    using Topro.Log;
    using Topro.Util;

    /// <summary>
    /// 出库业务接口实现
    /// </summary>
    public class StockOutServiceImpl:StockOutService
    {
        #region 注入

        /// <summary>
        /// 
        /// </summary>
        private readonly IUId _uid;

        /// <summary>
        /// db
        /// </summary>
        private readonly IDb _db;

        /// <summary>
        /// loggerService
        /// </summary>
        private readonly LoggerService _loggerService;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dapperFactory"></param>
        /// <param name="logger"></param>
        public StockOutServiceImpl(IDb db, LoggerService loggerService, IUId uid)
        {
            _uid = uid;
            _db = db;
            _loggerService = loggerService;
        }
        #endregion

        /// <summary>
        /// 出库
        /// </summary>
        /// <param name="request"></param>
        public JResult Save(StockOutSaveRequest stockOut)
        {
            var result = new JResult()
            {
                Success = false
            };

            //创建连接池
            var dbConnection = _db.DbConnection;
            //开始事务
            var transaction = _db.Begin(dbConnection);
            try
            {
                #region 表单验证
                //订单编号
                if (string.IsNullOrEmpty(stockOut.OrderId))
                    throw new Exception("出库单号不能为空.");
                //订单编号
                if (string.IsNullOrEmpty(stockOut.ResourceId))
                    throw new Exception("请选择出库单.");
                #endregion

                #region 仓位分配
                //库存
                var inventorys = dbConnection.Query<InventoryResponse>("select * from t_inventory where ResourceId=@ResourceId", new { ResourceId = stockOut.ResourceId }, transaction).ToList();
                if (inventorys == null)
                    throw new Exception("库存单据不存在.");
                //获取TopOne
                var inventory = inventorys.FirstOrDefault();
                if (inventory == null)
                    throw new Exception("库存单据不存在.");
                if(inventory.InventoryQty<=0)
                    throw new Exception("库存单据不存在或已完成.");
                //所有库位记录
                var warehouseUnits = _db.DbConnection.Query<WarehouseUnit>("select Id,Type,Code,Pai,Lie,Ceng,Locked,ContainerCode,IsContainer from t_warehouseunit where status=1 order by Pai,Lie,Ceng ASC", transaction);
                if (warehouseUnits == null && warehouseUnits.Any())
                    throw new Exception("暂无空闲仓位.");
                //库位
                var warehouseUnit = warehouseUnits.FirstOrDefault(c=>c.Id == inventory.WarehouseUnitId);
                if (warehouseUnit == null)
                    throw new Exception("库位不存在或已占用.");
                //日志
                _loggerService.Add(new OperLog()
                {
                    Level = 10,
                    Source = 10,
                    Message = $"创建出库单{stockOut.OrderId},仓位{warehouseUnit.Code}-之前是否锁定({warehouseUnit.Locked})",
                    Exception = "",
                    Ip = "127.0.0.1",
                    CreatedBy = stockOut.CreatedBy
                });
                //from
                var from = warehouseUnit.Code;

                //订单
                if (inventorys != null && inventorys.Any())
                {
                    inventorys.ForEach(item => {
                        var resourceId = dbConnection.Insert<Inventory>(new Inventory()
                        {
                            OrderType = (int)InventoryType.出库,
                            ResourceId = stockOut.OrderId,
                            SourceId = inventory.ResourceId,
                            WarehouseUnitId = item.WarehouseUnitId,
                            ContainerCode = item.ContainerCode,
                            IsContainer = item.IsContainer,
                            PartNo = item.PartNo,
                            ProductName = item.ProductName,
                            Qty = item.Qty,
                            LotNo = item.LotNo,
                            Grade = item.Grade,
                            Status = (int)InventoryStatus.待处理,
                            Remark = stockOut.Remark,
                            CreatedBy = stockOut.CreatedBy,
                            CreateTime = DateTime.Now
                        }, transaction);
                        if (resourceId <= 0)
                        {
                            throw new Exception("操作库存失败.");
                        }
                    });
                }
                #endregion

                #region 更新库存
                int updateInventoryStatus = dbConnection.Execute("UPDATE t_inventory SET InventoryQty=0 WHERE ResourceId=@ResourceId", new { ResourceId = inventory.ResourceId }, transaction);
                if (updateInventoryStatus <= 0)
                    throw new Exception("更新库存信息失败");
                #endregion

                #region 日志
                {
                    _loggerService.Add(new OperLog()
                    {
                        Level = 10,
                        Source = 10,
                        Message = $"创建出库单{stockOut.OrderId},仓位{warehouseUnit.Pai}-{warehouseUnit.Lie}-{warehouseUnit.Ceng}",
                        Exception = "",
                        Ip = "127.0.0.1",
                        CreatedBy = stockOut.CreatedBy
                    });
                }
                #endregion

                #region 指令
                var asrsjob = new ASRSJOB()
                {
                    BINDID = stockOut.OrderId,
                    TYPE = "Out",
                    CTNCODE = inventory.ContainerCode.ToString(),
                    ORIPORT = warehouseUnit.Code,
                    TARPORT = "",
                    STATE = (int)CommandStatus.待操作,
                    CREATEDATE = DateTime.Now,
                };

                if (stockOut.StationNo.Equals(1))
                    asrsjob.TARPORT = "1-10-01-01";
                else if (stockOut.StationNo.Equals(2))
                    asrsjob.TARPORT = "1-10-01-02";
                else if (stockOut.StationNo.Equals(3))
                    asrsjob.TARPORT = "1-10-01-03";
                else if (stockOut.StationNo.Equals(5))
                    asrsjob.TARPORT = "1-10-01-05";
                else if (stockOut.StationNo.Equals(7))
                    asrsjob.TARPORT = "1-10-01-07";
                else if (stockOut.StationNo.Equals(9))
                    asrsjob.TARPORT = "1-10-01-09";
                //新增
                var commandId = dbConnection.Insert<ASRSJOB>(asrsjob, transaction);
                if (commandId <= 0)
                    throw new Exception("操作失败.");
                #endregion

                result.Success = true;
                result.Message = "操作成功.";
                //提交事务
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();

                result.Success = false;
                result.Message = ex.Message;
            }
            finally
            {
                transaction.Dispose();
                dbConnection.Close();
                dbConnection.Dispose();
            }

            return result;
        }

        #region 获取未锁定记录
        /// <summary>
        /// 获取未锁定记录
        /// </summary>
        /// <returns></returns>
        public List<WarehouseUnit> GetNotLockeds(IDbTransaction transaction)
        {
            return _db.DbConnection.Query<WarehouseUnit>("select Id,Type,Code,Pai,Lie,Ceng,Locked from t_warehouseunit where Locked=@Locked order by Pai,Lie,Ceng", new { Locked = (int)WarehouseLocked.否 }, transaction).ToList();
        }
        #endregion

        #region 获取锁定记录
        /// <summary>
        /// 获取未锁定记录
        /// </summary>
        /// <returns></returns>
        public List<WarehouseUnit> GetLockeds(IDbTransaction transaction)
        {
            return _db.DbConnection.Query<WarehouseUnit>("select Id,Type,Code,Pai,Lie,Ceng,Locked from t_warehouseunit where Locked=@Locked order by Pai,Lie,Ceng", new { Locked = (int)WarehouseLocked.是 }, transaction).ToList();
        }
        #endregion

        #region 出库查询
        /// <summary>
        /// 出库查询
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public DataGrid<StockOutQueryResponse> Pager(StockOutQuery query)
        {
            var pageIndex = query.PageIndex <= 0 ? 0 : (query.PageIndex - 1) * query.PageSize;

            var files = "so.OrderId,so.WarehouseUnitId,CONCAT(wu.Pai,'-',wu.Lie,'-',wu.Ceng) as WarehouseUnitTostring,so.ProductName,so.ContainerType,so.IsContainer,so.Coordinate,so.Quantity,so.StationNo,so.Status,so.Remark,so.CreatedBy,(SELECT Account FROM user WHERE Id=so.CreatedBy) as CreatedByTostring,so.CreateTime";
            var tableName = "t_stockout so INNER JOIN t_warehouseunit wu ON so.WarehouseUnitId=wu.Id";
            var orderby = "ORDER BY so.CreateTime DESC";
            var where = "where 0=0";

            #region 条件
            if (query.Status.Any())
            {
                where += string.Format(" And so.Status in({0})", string.Join(",", query.Status));
            }
            #endregion

            var sb = new StringBuilder();

            sb.AppendFormat("SELECT COUNT(1) FROM {0} {1};", tableName, where);
            //sb.AppendFormat("select {0} from {1} {2} {3} offset {4} rows fetch next {5} rows only", files, tableName, where, orderby, pageIndex, query.PageSize);
            sb.AppendFormat("SELECT {0} FROM {1} {2} {3} LIMIT {4},{5};", files, tableName, where, orderby, pageIndex, query.PageSize);
            using (var multi = _db.DbConnection.QueryMultiple(sb.ToString()))
            {
                var count = multi.ReadFirst<int>();

                var list = multi.Read<StockOutQueryResponse>();

                return new DataGrid<StockOutQueryResponse>()
                {
                    Rows = list,
                    Total = count
                };
            }
        }
        #endregion
    }
}
